#include "cot_os.h"
#include <stdio.h>

#define LOG_PRINTF(fmt, arg...) printf("[%u ms][%u][%s:%d] " fmt "\r\n",  \
                                        GetTimerMs(),          \
                                        cotOs_Pid(),\
                                        __FUNCTION__, __LINE__,##arg)

#ifdef _WIN32
#include <windows.h>
size_t GetTimerMs(void) 
{
    return GetTickCount();
}
#else
#include <sys/time.h>
uint32_t GetTimerMs(void) 
{
    struct timeval tv;
    gettimeofday(&tv, NULL);
    return (uint32_t)(tv.tv_sec) * 1000 + (size_t)(tv.tv_usec) / 1000;
}
#endif


CotOSCondition_t g_cv;
uint8_t g_stackBuf[1024 * 10];
uint8_t g_stackBuf2[1024 * 10];
uint8_t g_stackBuf3[1024 * 10];

void taskfunc1(int arg)
{
    int t = 0;
    int t1 = 5;

    LOG_PRINTF("taskfunc-1-0: %p  %p\n", &t, &t1);

    while(1)
    {
        LOG_PRINTF("taskfunc-1-0\n");
        cotOs_ConditionWait(&g_cv);
        t++;
    }
}

void taskfunc2(int arg)
{
    int t = 5;

    LOG_PRINTF("taskfunc-2-0: %p\n", &t);

    while(t--)
    {
        LOG_PRINTF("taskfunc-2(%d)-0\n", arg);
        // cotOs_Wait(3000);
        LOG_PRINTF("taskfunc-2(%d)-1\n", arg);
        cotOs_Wait(1000);
        cotOs_ConditionNotify(&g_cv);
    }

    LOG_PRINTF("taskfunc-2-end\n");
}

void taskfunc3(int arg)
{
    static int t = 0;

    LOG_PRINTF("taskfunc-3-0: %p\n", &t);

    // while(1)
    {
        t++;
        
        // LOG_PRINTF("taskfunc-3-0: %d\n", t);
        // cotOs_Wait(1000);
        LOG_PRINTF("taskfunc-3-1\n");
        // cotOs_ConditionWait(&g_cv);
        cotOs_Wait(1000);
        // LOG_PRINTF("taskfunc-3-2\n");
        // cotOs_Wait(1000);
        // LOG_PRINTF("taskfunc-3-3\n");
        // cotOs_Wait(1000);
    }

    LOG_PRINTF("taskfunc-3-1 end\n");
}

void taskfunc4(int arg)
{
    static int t = 1;

    LOG_PRINTF("taskfunc-%d-0: %p\n", arg, &arg);

    while(t < 10)
    {
        t *= 2;
        LOG_PRINTF("taskfunc-%d-0 : %d\n", arg, t);
        cotOs_Wait(1000);
        // cotOs_Top();
    }

    LOG_PRINTF("taskfunc-%d-%d end\n", arg, t);
    // COT_OS_GET_STACK(sp);

    // LOG_PRINTF("taskfunc-%d-0: %lx\n", arg, sp);
}

void taskfunc5(int arg)
{
    LOG_PRINTF("taskfunc-%d-0\n", arg);

    cotOsTask_t task1 = cotOs_CreatTask(taskfunc4, "share_task4", 1);
    cotOsTask_t task2 = cotOs_CreatTask(taskfunc3, "share_task3", 2);

    // while(1)
    {
        LOG_PRINTF("taskfunc-%d-0\n", arg);
        cotOs_Wait(1000);
        cotOs_Join(task1);
        LOG_PRINTF("taskfunc-%d-0: task1 end\n", arg); 
        cotOs_Join(task2);
        LOG_PRINTF("taskfunc-%d-0: task2 end\n", arg);
    }

    LOG_PRINTF("taskfunc-%d-0 end\n", arg);
}

void taskfunc6(int arg)
{
    LOG_PRINTF("taskfunc-%d-0: %p\n", arg, &arg);

    while(1)
    {
        LOG_PRINTF("taskfunc-%d-0\n", arg);
        // cotOs_Wait(2000);
        cotOs_ConditionWait(&g_cv);
    }

    LOG_PRINTF("taskfunc-%d-0 end\n", arg);
}


int main(void)
{
    cotOs_Init(GetTimerMs);

    cotOs_ConditionInit(&g_cv);

    cotOs_CreatTaskWithStack(taskfunc2, "task2-1", g_stackBuf, sizeof(g_stackBuf), 1);
    cotOs_CreatTaskWithStack(taskfunc2, "task2-2", g_stackBuf2, sizeof(g_stackBuf2), 2);
    // cotOs_CreatTaskWithStack(taskfunc5, "task5", g_stackBuf3, sizeof(g_stackBuf3), 9);

    // cotOs_CreatTask(taskfunc2, "task2-1", 5);
    // cotOs_CreatTask(taskfunc2, "task2-2", 2);
    cotOs_CreatTask(taskfunc5, "task5", 9);


    printf("Start\n");

    cotOs_Start();

    printf("END\n");

    return 0;
}
